<?php

/*
 * connect to the database
 */
require "./includes/db_connection.php";

/*
 * SQL prepared queries
 */
$sql_check = "SELECT userid FROM user WHERE token=? AND username=?";
$sql_getuser = "SELECT userid, password FROM user WHERE username=?";
$sql_putuser = "INSERT INTO user(username, password, lastlog_dt, lastlog_ip, token) VALUES (?,?,NOW(),?, ?)";
$sql_getunits = "SELECT greenhouseid, name FROM greenhouse WHERE user_id=?";
$sql_putunit = "INSERT INTO greenhouse(user_id, name, token, request_cnf, update_cnf) VALUES(?,?,?,TRUE,FALSE)";
$sql_remunit = "DELETE FROM greenhouse WHERE greenhouseid=? AND user_id=?";
$sql_putcnf = "INSERT INTO config(greenhouse_id, type, number, v1, v2) VALUES(?, ?, ?, ?, ?)";
$sql_getcnf = "SELECT * FROM config WHERE greenhouse_id=?";
$sql_getrec = "SELECT * FROM record WHERE greenhouse_id=?";
$sql_requestallcnf = "UPDATE greenhouse SET request_cnf=TRUE WHERE user_id=?";
$sql_updatecnf = "UPDATE greenhouse SET update_cnf=TRUE WHERE greenhouseid=?";
$sql_checkowner = "SELECT greenhouseid FROM greenhouse WHERE user_id=? AND greenhouseid=?";
$sql_clearcnf = "DELETE FROM config WHERE greenhouse_id=?";
$sql_clearrec = "DELETE FROM record WHERE greenhouse_id=?";


/**
 * Get user id from received token
 *
 * @param string $token Communication unique token
 * @return integer User ID belonging to token
 */
function get_userid($token) {
	global $db;
	try {
		$ps = $db->prepare("SELECT userid FROM user WHERE token=?");
		$ps->execute(array($token));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get userid]\n$e");
	}
	return $row['userid'];
}

/**
 *
 * Generate new unique token for client communication
 *
 * @return string New 32 char token
 */
function generate_token() {
	global $db;
	try {
		$generate = true;
		while($generate) {
			/* generate token */
			$token = md5(uniqid(mt_rand()) . $_SERVER['REMOTE_ADDR']);

			/* check, that token is unique */
			$ps = $db->prepare("SELECT * FROM user WHERE token=?");
			$ps->execute(array($token));
			if(empty($ps->fetch())) {
				$generate = false;
			}
		}
		return $token;
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [generate token]\n$e");
	}
}

/**
 *
 * Generate new unique token for control unit communication
 *
 * @return string New 32 char token
 */
function unit_token() {
	global $db;

	$generate = true;
	while($generate) {
		/* generate token */
		$token = substr(md5(uniqid(mt_rand()) . $_SERVER['REMOTE_ADDR']), 0, 32);

		/* check, that token is unique */
		try {
			$ps = $db->prepare("SELECT * FROM greenhouse WHERE token=?");
			$ps->execute(array($token));
			if(empty($ps->fetch())) {
				$generate = false;
			}
		} catch (Exception $e) {
			die("<fail>\nChyba SQL [generate unit token]\n$e");
		}

	}

	return $token;

}



/**
 *
 * Register new user
 *
 * @param string $user User name
 * @param string $password User password (in MD5 format)
 */
function register($user, $password) {
	global $db, $sql_getuser, $sql_putuser;

	/* check that the username is unique */
	try {
		$ps = $db->prepare($sql_getuser);
		$ps->execute(array($user));
		if(!empty($ps->fetch(PDO::FETCH_ASSOC))) {
			die("<usrexist>");
		}
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get user]\n$e");
	}

	/* get unique token */
	$token = generate_token();

	/* insert new user */
	try {
		$ps = $db->prepare($sql_putuser);
		$ps->execute(array($user, $password, $_SERVER['REMOTE_ADDR'], $token));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [put user]\n$e");
	}

	/* send token to client */
	echo("<ok>\n$token");
}

/**
 *
 * Log in
 *
 * @param string $user User name
 * @param string $password User password
 */
function login($user, $password) {
	global $db, $sql_getuser;

	/* get user data from db */
	try {
		$ps = $db->prepare($sql_getuser);
		$ps->execute(array($user));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
		if(empty($row)) {
			die("<err>");
		}
		$userid = $row['userid'];
		$pass = $row['password'];
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get user]\n$e");
	}

	/* verify password */
	if($pass != $password) {
		die("<err>");
	}

	/* generate new token */
	$token = generate_token();

	/* insert token into db */
	try {
		$ps = $db->prepare("UPDATE user SET token=? WHERE userid=?");
		$ps->execute(array($token, $userid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [update token]\n$e");
	}
	/* send data to client */
	echo("<ok>\n$token");
}

/**
 * Check user token
 *
 * @param string $user User name
 * @param string $token Client token
 */
function check($user, $token) {
	global $db, $sql_check;

	try {
		$ps = $db->prepare($sql_check);
		$ps->execute(array($token, $user));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
		if(!empty($row)) {
			echo("<ok>\n");
		}
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [check token]\n$e");
	}
}

function checkowner($unitid, $userid) {
	global $db, $sql_checkowner;

	try {
		$ps = $db->prepare($sql_checkowner);
		$ps->execute(array($userid, $unitid));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
		if(empty($row)) {
			die("<fail>\nACCESS DENIED");
		}
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [check owner]\n$e");
	}
}

/**
 * Send server info
 *
 */
function getinfo() {

	/* send confirmation */
	echo("<ok>\n");
	/* send data to client */
	echo($_SERVER['HTTP_HOST']."\n".$_SERVER['SERVER_ADDR']);
}

/**
 * Send unit list to client
 *
 * @param string $token User communication token
 */
function unitlist($token) {
	global $db, $sql_getunits;

	/* get user id */
	$userid = get_userid($token);
	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* get units from db */
	try {
		$ps = $db->prepare($sql_getunits);
		$ps->execute(array($userid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get units]\n$e");
	}

	/* send data to client */
	echo("<ok>\n");
	foreach ($ps as $row) {
		echo($row['greenhouseid'] . " " . $row['name'] . "\n");
	}
}

/**
 * Add new unit into DB
 *
 * @param string $token User communication token
 * @param string $unitname Inserted unit name
 */
function addunit($token, $unitname) {
	global $db, $sql_putunit;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* generate token for unit */
	$unittoken = unit_token();

	/* insert unit into db */
	try {
		$ps = $db->prepare($sql_putunit);
		$ps->execute(array($userid, $unitname, $unittoken));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [put unit]\n$e");
	}

	/* send data to client */
	echo("<ok>\n$unittoken\n".$db->lastInsertId());
}

/**
 * Remove unit from DB
 *
 * @param string $token User communication token
 * @param string $unitid Removed unit ID
 */
function removeunit($token, $unitid) {
	global $db, $sql_remunit;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* remove unit from db */
	try {
		$ps = $db->prepare($sql_remunit);
		$ps->execute(array($unitid, $userid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [remove unit]\n$e");
	}

	/* send confirm to client */
	echo("<ok>");
}

/**
 * Get unit records from db
 *
 * @param string $token User communication token
 * @param string $unitid Unit ID number
 */
function getrec($token, $unitid) {
	global $db, $sql_getrec;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* get records from db */
	try {
		$ps = $db->prepare($sql_getrec);
		$ps->execute(array($unitid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get records]\n$e");
	}


	/* send data to client */
	echo("<ok>\n");
	foreach ($ps as $row) {
		echo($row['type'] . " " . $row['dt'] . " " . $row['v1'] . " " . $row['v2']  . " " . $row['v3'] . "\n");
	}
}

/**
 * Get unit config from db
 *
 * @param string $token User communication token
 * @param string $unitid Unit ID number
 */
function getcnf($token, $unitid) {
	global $db, $sql_getcnf;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* get records from db */
	try {
		$ps = $db->prepare($sql_getcnf);
		$ps->execute(array($unitid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get config]\n$e");
	}


	/* send data to client */
	echo("<ok>\n");
	foreach ($ps as $row) {
		echo($row['type'] . " " . $row['number'] . " " . $row['v1'] . " " . $row['v2'] . "\n");
	}
}


/**
 * Remove all config data of unit from db
 * 	and prepare space for a new config data
 *
 *
 * @param string $token User communication token
 * @param string $unitid Unit ID number
 */
function clearcnf($token, $unitid) {
	global $db, $sql_clearcnf;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* check unit owner */
	checkowner($unitid, $userid);

	try {
		$ps = $db->prepare($sql_clearcnf);
		$ps->execute(array($unitid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [clear config]\n$e");
	}

	/* send confirm to client */
	echo("<ok>");
}

/**
 * Remove all records data of unit from db
 *
 *
 * @param string $token User communication token
 * @param string $unitid Unit ID number
 */
function clearrec($token, $unitid) {
	global $db, $sql_clearrec;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* check unit owner */
	checkowner($unitid, $userid);


	try {
		$ps = $db->prepare($sql_clearrec);
		$ps->execute(array($unitid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [clear records]\n$e");
	}

	/* send confirm to client */
	echo("<ok>");
}

/**
 * Parse config data from client
 *
 * @param string $token User communication token
 * @param string $unitid Unit ID number
 * @param string $data Configuration data from client
 */
function sendcnf($token, $unitid, $data) {
	global $db, $sql_putcnf;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}

	/* parse config string */
	$splited = explode(" ", $data);
	if(count($splited) > 2) {
		$type = $splited[0];
		$num = $splited[1];
		$val1 = $splited[2];

		if(count($splited) > 3) {
			$val2 = $splited[3];
		}
		else {
			$val2 = "0";
		}

		try {
			$ps = $db->prepare($sql_putcnf);
			$ps->execute(array($unitid, $type, $num, $val1, $val2));
		} catch (Exception $e) {
			die("<fail>\nChyba SQL [send config]\n$e");
		}

		/* send confirm to client */
		echo("<ok>");
	}
	else {
		die("<fail>\nChyba vstupnich dat\n$data");
	}
}

/**
 * Set request config flag to all user's greenhouses
 * 
 * 
 * @param string $token User communication token
 */
function requestallcnf($token) {
	global $db, $sql_requestallcnf;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}
	
	try {
		$ps = $db->prepare($sql_requestallcnf);
		$ps->execute(array($userid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [request all config]\n$e");
	}

	/* send confirm to client */
	echo("<ok>");
}

function updatecnf($token, $unitid) {
	global $db, $sql_updatecnf;

	/* get user id */
	$userid = get_userid($token);

	if(empty($userid)) {
		die("<tokenerr>");
	}
	try {
		$ps = $db->prepare($sql_updatecnf);
		$ps->execute(array($unitid));
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [update config]\n$e");
	}

	/* send confirm to client */
	echo("<ok>");
}



/**
 *
 *   BODY
 *
 */

/*
 * Get input data from client
 */
$action = $_POST['action'];
$user = $_POST['user'];
$pass = $_POST['pass'];
$token = $_POST['token'];
$unitid = $_POST['unitid'];
$unitname = $_POST['unitname'];
$data = $_POST['data'];

/*
 * Select action
 */

switch($action) {
	case 'register' :
		register($user, $pass);
		break;

	case 'login' :
		login($user, $pass);
		break;

	case 'check' :
		check($user, $token);
		break;

	case 'getinfo' :
		getinfo();
		break;

	case 'unitlist' :
		unitlist($token);
		break;

	case 'addunit' :
		addunit($token, $unitname);
		break;

	case 'removeunit' :
		removeunit($token, $unitid);
		break;

	case 'getrec' :
		getrec($token, $unitid);
		break;

	case 'clearrec' :
		clearrec($token, $unitid);
		break;

	case 'getcnf' :
		getcnf($token, $unitid);
		break;

	case 'clearcnf' :
		clearcnf($token, $unitid);
		break;

	case 'sendcnf' :
		sendcnf($token, $unitid, $data);
		break;

	case 'requestcnf' :
		requestallcnf($token);
		break;

	case 'updatecnf' :
		updatecnf($token, $unitid);
		break;
}

exit();
?>